/**
 * 
 */
package org.compiere.model;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;

import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;

import extend.org.compiere.utils.Util;

/**
 * @author V.Sokolov
 *
 */
public class MBPMProject extends X_BPM_Project{
	/**
	 * 
	 */
	private static final long serialVersionUID = -7041996758972564192L;
	/** */
	public static final int TempProjectID = 1000;  // TODO The temp project to preliminary calculations

	/**
	 * @param ctx
	 */
	public MBPMProject(Properties ctx) {
		super(ctx);
	}

	/**
	 * @param ctx
	 * @param BPM_Project_ID
	 * @param trxName
	 */
	public MBPMProject(Properties ctx, int BPM_Project_ID, String trxName) {
		super(ctx, BPM_Project_ID, trxName);
	}
	
	/**
	 * @param ctx
	 * @param rs
	 * @param trxName
	 */
	public MBPMProject(Properties ctx, ResultSet rs, String trxName) {
		super(ctx, rs, trxName);
	}
	
	/* 
	 */
	@Override
	protected boolean beforeSave(boolean newRecord) {
		
		String errmsg = "";
		if(getAGR_Dispatcher_ID() == 0) errmsg = Util.requiredField(COLUMNNAME_AGR_Dispatcher_ID)+"\n";
		Util.checkErrMsg(errmsg);
		
		if(newRecord && isWork()){
			MBPMProject[] pr = getActualProject(getCtx(), getBPM_VersionBudget_ID(), get_TrxName());
			if(pr.length != 0 && getBPM_Parent_ID() == 0)
				errmsg = Util.requiredField(COLUMNNAME_BPM_Parent_ID)+"\n";
			Util.checkErrMsg(errmsg);		
		}
		
		return true;
	}
	
	/* 
	 */
	@Override
	protected boolean afterSave(boolean newRecord, boolean success) {
		
		if(newRecord && success){
			
			MBPMForm[] formLine = MBPMFormLine.getLineForm(getCtx(), getBPM_VersionBudget_ID(), null, get_TrxName());
			if(formLine.length == 0)
				throw new  AdempiereException("Отсутствуют настройки по формам");
			
			for(MBPMForm f: formLine){
				MBPMProjectLine pLine = new MBPMProjectLine(getCtx(), 0, get_TrxName());
				pLine.setBPM_Form_ID(f.getBPM_Form_ID());
				pLine.setBPM_Project_ID(getBPM_Project_ID());
				pLine.saveEx();
			}
		}
		
		if(newRecord){
			copyBudgetCall(getBPM_Parent_ID());
			copyBPM_Project_Agreement(getBPM_Parent_ID());
			for(MOrg org : getDZO(Env.getAD_Client_ID(getCtx()),false))
			{
				copyBPM_FormValues(org.get_ID(), getBPM_Parent_ID()
									, new MBPMProject(getCtx(), getBPM_Parent_ID()
											, get_TrxName()).getBPM_VersionBudget_ID());
			}
		}
		
		return true;
	}
	
	/* 
	 */
	@Override
	protected boolean afterDelete(boolean success) {
	
		// Delete records Budget Call
		if(success && getBPM_Parent_ID() != 0){
			
			StringBuilder sql = new StringBuilder();
			sql.append("DELETE FROM ");
			sql.append(I_BPM_BudgetCall.Table_Name);
			sql.append(" WHERE \n");
			sql.append(I_BPM_BudgetCall.COLUMNNAME_BPM_Project_ID).append("=").append(getBPM_Project_ID());
			
			DB.executeUpdate(sql.toString(), get_TrxName());
		}
		
		return true;
	}
	
	private void copyBudgetCall(int BPM_Parent_ID){
		
		MBPMBudgetCall[] call = MBPMBudgetCall.getBudgetCallProject(BPM_Parent_ID); 
		for(MBPMBudgetCall c: call){
			MBPMBudgetCall newCall = new MBPMBudgetCall(getCtx(), 0, get_TrxName());
			PO.copyValues(c, newCall);
			newCall.setBPM_Parent_ID(BPM_Parent_ID);
			newCall.setBPM_Project_ID(getBPM_Project_ID());
			newCall.setBPM_VersionBudgetLine_ID(MBPMVersionBudget.getCurrentVersion());
			newCall.setProcessed(c.isProcessed());//newCall.setProcessed(false);
			newCall.setIsActive(c.isActive());//newCall.setIsActive(true);
			newCall.setDocStatus(c.getDocStatus());//newCall.setDocStatus(null);
			newCall.setAGR_Stage_ID(c.getAGR_Stage_ID());//newCall.setAGR_Stage_ID(0);
			newCall.setAD_Org_ID(c.getAD_Org_ID());
			newCall.save();
			//attachment file
			MAttachment mAttachmentCall = MAttachment.get(getCtx(), c.get_Table_ID(), c.get_ID());
			if(mAttachmentCall!=null){
				MAttachment newAttachmentCall = new MAttachment(getCtx(), 0, get_TrxName());
				PO.copyValues(mAttachmentCall, newAttachmentCall);
				newAttachmentCall.setAD_Org_ID(mAttachmentCall.getAD_Org_ID());
				newAttachmentCall.setRecord_ID(newCall.get_ID());
				for(MAttachmentEntry entry : mAttachmentCall.getEntries())
				{
					newAttachmentCall.addEntry(entry.getFile());
				}
				newAttachmentCall.saveEx();
			}
			//
			MBPMBudgetCallLine[] callLine = MBPMBudgetCall.getLines(getCtx(), c.getBPM_BudgetCall_ID(), get_TrxName());
			for(MBPMBudgetCallLine cl: callLine){
				MBPMBudgetCallLine newCallLine = new MBPMBudgetCallLine(getCtx(), 0, get_TrxName());
				PO.copyValues(cl, newCallLine);
				newCallLine.setBPM_BudgetCall_ID(newCall.getBPM_BudgetCall_ID());
				newCallLine.setProcessed(false);
				newCallLine.setIsActive(true);
				newCallLine.setAD_Org_ID(cl.getAD_Org_ID());
				newCallLine.saveEx();
				
				//attachment file
				MAttachment mAttachmentCallLine = MAttachment.get(getCtx(), cl.get_Table_ID(), cl.get_ID());
				if(mAttachmentCallLine!=null){
					MAttachment newAttachmentCallLine = new MAttachment(getCtx(), 0, get_TrxName());
					PO.copyValues(mAttachmentCallLine, newAttachmentCallLine);
					newAttachmentCallLine.setAD_Org_ID(mAttachmentCallLine.getAD_Org_ID());
					newAttachmentCallLine.setRecord_ID(newCallLine.get_ID());
					for(MAttachmentEntry entry : mAttachmentCallLine.getEntries())
					{
						newAttachmentCallLine.addEntry(entry.getFile());
					}
					newAttachmentCallLine.saveEx();
				}
				//
			}
		}
		
	}

	private void copyBPM_Project_Agreement(int BPM_Parent_ID){
		if(BPM_Parent_ID>0){
			MBPMProjectAgreement[] projectAgreements = MBPMProjectAgreement.getBPMProjectAgreements(BPM_Parent_ID);
			for(MBPMProjectAgreement projectAgreement : projectAgreements)
			{
				MBPMProjectAgreement newProjectAgreement = new MBPMProjectAgreement(getCtx(), 0, get_TrxName());
				PO.copyValues(projectAgreement, newProjectAgreement);
				newProjectAgreement.setBPM_Project_ID(getBPM_Project_ID());
				newProjectAgreement.setProcessed(false);
				newProjectAgreement.setAGR_Stage_ID(0);
				newProjectAgreement.setDocStatus(null);
				newProjectAgreement.setIsActive(true);
				newProjectAgreement.setAD_Org_ID(projectAgreement.getAD_Org_ID());
				newProjectAgreement.saveEx();
			}	
		}else{
			for(MOrg org : getDZO(Env.getAD_Client_ID(getCtx()),true))
			{
				MBPMProjectAgreement newProjectAgreement = new MBPMProjectAgreement(getCtx(), 0, get_TrxName());
				newProjectAgreement.setAD_Client_ID(Env.getAD_Client_ID(getCtx()));
				newProjectAgreement.setAD_Org_ID(org.get_ID());
				newProjectAgreement.setBPM_Project_ID(getBPM_Project_ID());
				newProjectAgreement.setDescription("Согласование бюджетных форм.");
				newProjectAgreement.setAGR_Dispatcher_ID(1000003);
				newProjectAgreement.saveEx();
				
			}
			//
			MBPMProjectAgreement newProjectAgreement = new MBPMProjectAgreement(getCtx(), 0, get_TrxName());
			newProjectAgreement.setAD_Client_ID(Env.getAD_Client_ID(getCtx()));
			newProjectAgreement.setAD_Org_ID(0);
			newProjectAgreement.setBPM_Project_ID(getBPM_Project_ID());
			newProjectAgreement.setDescription("Согласование бюджетных форм.");
			newProjectAgreement.setAGR_Dispatcher_ID(1000003);
			newProjectAgreement.saveEx();
			//
		}
	}
	
	private void copyBPM_FormValues(int AD_Org_ID,int BPM_Project_ID, int BPM_VersionBudget_ID){
		MBPMFormValues[] formValues = MBPMFormValues.getFormValues(AD_Org_ID, BPM_Project_ID, BPM_VersionBudget_ID);
		for(MBPMFormValues formValue: formValues)
		{
			MBPMFormValues newFormValue = new MBPMFormValues(getCtx(), 0, get_TrxName());
			PO.copyValues(formValue, newFormValue);
			newFormValue.setCellValue("0");
			newFormValue.setCellValue(formValue.getCellValue()==null?"0":formValue.getCellValue());
			newFormValue.setBPM_Project_ID(getBPM_Project_ID());
			newFormValue.setBPM_VersionBudget_ID(getBPM_VersionBudget_ID());
			newFormValue.setAD_Org_ID(AD_Org_ID);
			newFormValue.saveEx();
		}
	}
	public static MBPMProjectLine[] getLines(Properties ctx, int BPM_Project_ID, String category, String trxName){
		
		String whereCause = "";
		if(category != null)
			whereCause = " AND "+I_BPM_Form.COLUMNNAME_BPM_Form_ID+" in (select BPM_Form_ID from BPM_Form where \n " +
						 "BPM_Form_ID in (select BPM_FormCode_ID from bpm_formCode where categoryname='"+category+"'))";
		
		List<MBPMProjectLine> list = new Query(ctx, I_BPM_ProjectLine.Table_Name, I_BPM_ProjectLine.COLUMNNAME_BPM_Project_ID+"=? "+whereCause, trxName)
		.setParameters(BPM_Project_ID)
		.setOnlyActiveRecords(true)
		.list();
		
		MBPMProjectLine[] retValue = new MBPMProjectLine[list.size ()];
		
		list.toArray(retValue);
		
		return retValue;
		
	}
	
	public static boolean isLineForm(Properties ctx, int BPM_Project_ID, int BPM_Form_ID, String trxName){
		
		List<MBPMProjectLine> line = new Query(ctx, I_BPM_ProjectLine.Table_Name, I_BPM_Project.COLUMNNAME_BPM_Project_ID+"=? AND "
																				 +I_BPM_ProjectLine.COLUMNNAME_BPM_Form_ID+"=?", trxName)
		.setParameters(BPM_Project_ID, BPM_Form_ID).list();
		
		return (line.size() != 0);
	}
	
	public static MBPMProject[] getActualProject(Properties ctx, int BPM_VersionBudget_ID, String trxName){
		
		List<MBPMProject> list = new Query(ctx, I_BPM_Project.Table_Name, I_BPM_Project.COLUMNNAME_BPM_VersionBudget_ID+"=? AND "
																		  +I_BPM_Project.COLUMNNAME_isActual+"=?", trxName)
		.setParameters(BPM_VersionBudget_ID, "Y")
		.setOnlyActiveRecords(true)
		.list();
		
		MBPMProject[] retValue = new MBPMProject[list.size ()];
		
		list.toArray(retValue);
		
		return retValue;
		
	}
	
	public static MBPMProject[] getWorkProject(Properties ctx, int BPM_VersionBudget_ID, String trxName){
		
		List<MBPMProject> list = new Query(ctx, I_BPM_Project.Table_Name, I_BPM_Project.COLUMNNAME_BPM_VersionBudget_ID+"=? AND "
																		  +I_BPM_Project.COLUMNNAME_isWork+"=?", trxName)
		.setParameters(BPM_VersionBudget_ID, "Y")
		.setOnlyActiveRecords(true)
		.list();
		
		MBPMProject[] retValue = new MBPMProject[list.size ()];
		
		list.toArray(retValue);
		
		return retValue;
	}
	
	private MOrg[] getDZO(int AD_Client_ID, boolean IsAll){
	    PreparedStatement pstmt = null;
		ResultSet rs = null;
		MOrg result = null;
		ArrayList<MOrg> list = new ArrayList<MOrg>();
		
		String sql_ = "SELECT * FROM "+X_AD_Org.Table_Name+" \n WHERE ";
		if(!IsAll)
			sql_=sql_+" AD_Org_ID NOT IN(0,1000000) AND ";
		sql_ = sql_+X_AD_Org.COLUMNNAME_AD_Client_ID+"="+AD_Client_ID;
		try
		{
			pstmt = DB.prepareStatement(sql_,null);
			rs = pstmt.executeQuery();	
			while(rs.next()){
				result = new MOrg(Env.getCtx(), rs, null);
				list.add(result);
			}				
		}
		catch (SQLException e)
		{
			CLogger.get().log(Level.INFO, "MOrg", e);
		}
		finally
		{
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}	
		
		return list.toArray(new MOrg[list.size()]);
	}

	private MBPMBudgetCall[] m_lines = null;
	
	public MBPMBudgetCall[] getBudgetCalls(boolean requery)
	{
		if (m_lines != null && !requery) {
			set_TrxName(m_lines, get_TrxName());
			return m_lines;
		}
		List<MBPMBudgetCall> list = new Query(getCtx(), I_BPM_BudgetCall.Table_Name, "BPM_Project_ID = ?", get_TrxName())
										.setParameters(get_ID())
										.setOrderBy(I_BPM_BudgetCall.COLUMNNAME_BPM_BudgetCall_ID)
										.list();
		m_lines = list.toArray(new MBPMBudgetCall[list.size()]);
		return m_lines;
	}
}
